package com.dynamicthreadpool.spring;

import com.dynamicthreadpool.netty.server.ThreadPoolControlServer;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

/**
 * 动态线程池执行器，参考XXL-JOB的XxlJobSpringExecutor实现
 * 实现SmartInitializingSingleton接口，在Spring容器初始化完成后自动启动
 */
public class DynamicThreadPoolExecutor implements ApplicationContextAware, InitializingBean, SmartInitializingSingleton {

    private ApplicationContext applicationContext;
    
    // 配置参数
    private int port = 8888; // 默认端口
    private String adminAddresses;
    private String accessToken;
    private String appname;
    
    // 内部属性
    private ThreadPoolControlServer embedServer;
    private boolean initialized = false;
    private boolean started = false;
    
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }
    
    @Override
    public void afterPropertiesSet() throws Exception {
        // 初始化配置
        initConfig();
    }
    
    @Override
    public void afterSingletonsInstantiated() {
        // 在Spring容器中所有单例Bean初始化完成后调用
        start();
    }
    
    /**
     * 初始化配置
     */
    private void initConfig() {
        // 从Spring环境变量或配置文件中获取配置
        System.out.println("DynamicThreadPoolExecutor: init config");
        initialized = true;
    }
    
    /**
     * 启动执行器
     */
    public void start() {
        if (!initialized || started) {
            return;
        }
        
        System.out.println("DynamicThreadPoolExecutor: start");
        
        try {
            // 1. 初始化嵌入式服务器
            initEmbedServer();
            
            // 2. 其他初始化操作（如果需要）
            // 可以在这里添加日志初始化、心跳检测等功能
            
            started = true;
            System.out.println("DynamicThreadPoolExecutor: start success");
        } catch (Exception e) {
            System.err.println("DynamicThreadPoolExecutor: start failed");
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
    
    /**
     * 初始化嵌入式服务器
     */
    private void initEmbedServer() throws Exception {
        // 检查必要参数
        if (port <= 0) {
            System.out.println("DynamicThreadPoolExecutor: port invalid, skip embed server init.");
            return;
        }
        
        // 创建并启动Netty服务器，传递accessToken配置
        embedServer = new ThreadPoolControlServer(port, accessToken);
        
        // 使用单独的线程启动服务器，避免阻塞主线程
        Thread thread = new Thread(() -> {
            try {
                embedServer.start();
            } catch (Exception e) {
                System.err.println("DynamicThreadPoolExecutor: embed server start failed");
                e.printStackTrace();
            }
        }, "DynamicThreadPool-EmbedServer");
        thread.setDaemon(true);
        thread.start();
        
        System.out.println("DynamicThreadPoolExecutor: embed server started on port " + port + ", accessToken enabled: " + 
                (accessToken != null && !accessToken.isEmpty()));
    }
    
    /**
     * 停止执行器
     */
    public void stop() {
        if (!started) {
            return;
        }
        
        System.out.println("DynamicThreadPoolExecutor: stop");
        
        try {
            // 停止嵌入式服务器
            if (embedServer != null) {
                embedServer.stop(); // 关闭服务器通道
                // 注意：由于Netty服务器在独立线程中运行，shutdown会在start方法的finally块中自动调用
                System.out.println("DynamicThreadPoolExecutor: embed server stopped");
            }
            
            started = false;
            System.out.println("DynamicThreadPoolExecutor: stop success");
        } catch (Exception e) {
            System.err.println("DynamicThreadPoolExecutor: stop failed");
            e.printStackTrace();
        }
    }
    
    // Getters and Setters
    public int getPort() {
        return port;
    }
    
    public void setPort(int port) {
        this.port = port;
    }
    
    public String getAdminAddresses() {
        return adminAddresses;
    }
    
    public void setAdminAddresses(String adminAddresses) {
        this.adminAddresses = adminAddresses;
    }
    
    public String getAccessToken() {
        return accessToken;
    }
    
    public void setAccessToken(String accessToken) {
        this.accessToken = accessToken;
    }
    
    public String getAppname() {
        return appname;
    }
    
    public void setAppname(String appname) {
        this.appname = appname;
    }
}